<link rel="import" href="../../polymer/polymer-element.html">
<link rel="import" href="../../polymer/lib/elements/dom-if.html">
<link rel="import" href="../../polymer/lib/elements/dom-repeat.html">
<link rel="import" href="theme.html">

<dom-module id="hakuneko-connectors">

    <template>
        <style include="theme"></style>
        <style>
            :host {
                /*background-color: var(--menu-control-background-color);*/
                flex: 1;
            }
            .popup {
                flex-direction: column;
                position: absolute;
                left: 0;
                right: 0;
                top: 0;
                bottom: 0;
                border: var(--connector-dialog-border);
                background-color: var(--connector-dialog-background-color);
                padding: 0em;
                margin: 1em;
                border-radius: 0em;
                -webkit-box-shadow: var(--connector-dialog-shadow);
                   -moz-box-shadow: var(--connector-dialog-shadow);
                        box-shadow: var(--connector-dialog-shadow);
                z-index: 1;
            }
            .show {
                display: flex;
            }
            .hide {
                display: none;
            }
            .button {
                cursor: pointer;
            }
            .link {
                margin-left: 0.5em;
            }
            .active {
                cursor: pointer;
            }
            .disabled {
                cursor: not-allowed;
                opacity: 0.25;
            }
            .clear {
                color: var(--connector-button-clear-color);
            }
            .controls {
                flex: 0;
                text-align: right;
                padding: 0.5em;
            }
            .content {
                flex: 1;
                display: flex;
                flex-direction: row;
                overflow-y: hidden; /* Fixes overflow scrolling issue in flexbox, because inherited value is 'visible' */
            }
            .filters {
                flex: 0;
                display: flex;
                flex-direction: column;
                margin: 0.5em;
                max-height: 100%; /* Fixes overflow scrolling issue in flexbox with Chromium 73+ => https://support.google.com/chrome/thread/3101009?msgid=4942418 */
            }
            .connectors {
                flex: 1;
                display: flex;
                flex-direction: column;
                margin: 0.5em;
                max-height: 100%; /* Fixes overflow scrolling issue in flexbox with Chromium 73+ => https://support.google.com/chrome/thread/3101009?msgid=4942418 */
            }
            .pattern {
                flex: 0;
                width: 100%;
                min-width: 16em;
            }
            .scroll {
                flex: 1;
                overflow-y: scroll;
            }
            .tags {
                background-color: var(--connector-tag-list-background-color);
                line-height: 1.5em;
                padding: 0.5em;
            }
            .separator {
                flex: 0;
                font-weight: bold;
                color: var(--connector-dialog-category-color);
                border-bottom: var(--connector-dialog-separator);
                /*margin-bottom: 0.5em;*/
                padding-left: 0.5em;
                padding-top: 0.5em;
                padding-bottom: 0.25em;
                text-transform: uppercase;
            }
            .card {
                display: flex;
                flex-direction: row;
                width: 30em;
                float: left;
                background-color: var(--connector-card-background-color);
                border: var(--connector-card-border);
                -webkit-box-shadow: var(--connector-card-shadow);
                   -moz-box-shadow: var(--connector-card-shadow);
                        box-shadow: var(--connector-card-shadow);
                margin: 1em;
                padding: 0.5em;
            }
            .card:hover {
                background-color: var(--connector-card-highlighted);
            }
            .cardSelected {
                background-color: var(--connector-card-selected) !important;
            }
            .icon {
                width: 3.25em;
                height: 3.25em;
            }
            .description {
                flex: 1;
                margin-left: 0.5em;
            }
            .heading {
                display: flex;
                flex-direction: row;
                flex: 0;
                margin-bottom: 0.25em;
                border-bottom: var(--connector-title-border);
            }
            .title {
                flex: 1;
                font-size: 1.25em;
                font-weight: bold;
            }
            .control {
                flex: 0;
                white-space: nowrap;
            }
            .tag {
                white-space: nowrap;
                color: var(--connector-tag-color);
                background-color: var(--connector-tag-background-color);
                /*border: var(--connector-tag-border);*/
                border-radius: 0.5em;
                padding-left: 0.3em;
                padding-right: 0.3em;
            }
            .tagSelected {
                background-color: var(--connector-tag-selected) !important;
            }
        </style>
        <input type="text" class="button" on-click="showPopup" value$="[[ selectedConnector.label ]]" readonly />
        <div class$="popup [[ getPopupClass(popupVisibility) ]]">
            <div class="controls" title="Click to cancel the website selection">
                <i class="fas fa-times-circle fa-2x button" on-click="closePopup"></i>
            </div>
            <div class="content">
                <div class="filters">
                    <div class="separator">
                        <i class="fas fa-plug"></i>
                        <label>Website</label>
                    </div>
                    <input id="connectorPattern" class="pattern" type="text" value="{{ connectorPattern::input }}"  title="Show only websites with a name that matches the entered pattern (case-insensitive)"/>
                    <div class="separator">
                        <i class="fas fa-book"></i>
                        <label>Manga</label>
                    </div>
                    <input id="mangaPattern" class="pattern" type="text" value="{{ mangaPattern::input }}" on-keyup="filterConnectorsByManga" title="Show only websites with a manga that matches the entered pattern (case-insensitive)&#10;Searches only in local synchronized manga lists&#10;Press ENTER to perform the search"/>
                    <div class="separator">
                        <i class="fas fa-tags" title="Show only websites containing the selected tags"></i>
                        <label>Tags</label>
                    </div>
                    <div class="scroll tags">
                        <template is="dom-repeat" items="[[ tags ]]">
                            <span class$="tag button [[ getTagClass(selectedTags, item) ]]" on-click="toggleTag">[[ item.tag ]]</span>
                        </template>
                    </div>
                </div>
                <div class="connectors">
                    <div class="separator">
                        <i class="fas fa-times button clear" title="Reset all filters" on-click="clearFilters"></i>
                        <label>Connectors</label>
                    </div>
                    <div class="scroll">
                        <template is="dom-repeat" items="[[ connectorList ]]" filter="[[ filterConnectors(connectorPattern, selectedTags) ]]">
                            <div class$="card [[ getConnectorClass(selectedConnector, item) ]]" title$="Click to show mangas from this website&#10;&#10;Label: [[ item.label ]]&#10;ID: [[ item.id ]]&#10;URL: [[ item.url ]]" on-click="selectConnector">
                                <img class="icon" src$="[[ item.icon ]]" onerror="this.src='/img/connectors/default';" />
                                <div class="description">
                                    <div class="heading">
                                        <div class="title">[[ item.label ]]</div>
                                        <div class="control">
                                            <i class$="fas fa-sign-in-alt link [[ getLoginClass(item.links) ]]" title="Click to open the login page" on-click="openLogin"></i>
                                            <i class$="fas fa-coffee link [[ getDonationClass(item.links) ]]" title="Click to open the donation page" on-click="openDonation"></i>
                                            <i class="fas fa-external-link-square-alt link active" title="Click to open the website in a new window&#10;This can be useful for various taks e.g.&#10;&#10;&#8226; Check / Investigate the website status&#10;&#8226; Bypass CloudFlare protection&#10;&#8226; Unlock a Captcha" on-click="openWebsite"></i>
                                        </div>
                                    </div>
                                    <div>
                                        <template is="dom-repeat" items="[[ item.tags ]]">
                                            <span class="tag">[[ item ]]</span>
                                        </template>
                                    </div>
                                </div>
                            </div>
                        </template>
                    </div>
                </div>
            </div>
        </div>
    </template>

    <script>
        /** @polymerElement */
        class HakunekoConnectors extends Polymer.Element {
            /**
             *
             */
            static get is() {
                return 'hakuneko-connectors';
            }

            /**
             *
             */
            static get properties() {
                return {
                    selectedConnector: {
                        type: Object,
                        value: Engine.Connectors[0],
                        notify: true, // enable upward data flow,
                        //readOnly: true // prevent downward data flow
                    }
                };
            }

            /**
             *
             */
            ready() {
                super.ready();
                this.popupVisibility = false;
                // list of all available connectors
                this.connectorList = [];
                // load connectors
                this.set( 'connectorList', Engine.Connectors );
                this.tags = this.getAvailableTags();
                this.selectedTags = [];
            }

            /**
             * 
             */
            getAvailableTags() {
                let tags = this.connectorList.reduce( ( accumulator, connector ) => {
                    let newTags = connector.tags.filter( t => !accumulator.includes( t ) );
                    return accumulator.concat( newTags );
                }, [] );
                // SET removes duplicates
                return [...new Set( tags )].sort().map( t => {
                    return {
                        tag: t,
                        selected: false
                    };
                } );
            }

            /**
             *
             */
            getPopupClass( visibility ) {
                return ( visibility ? 'show' : 'hide' );
            }

            /**
             *
             */
            showPopup() {
                //this.clearFilters();
                this.set( 'popupVisibility', true );
                //this.set( 'connectorPattern', '' );
                this.$.connectorPattern.select();
                this.$.connectorPattern.focus();
            }

            /**
             *
             */
            closePopup() {
                this.set( 'popupVisibility', false );
            }

            /**
             *
             */
            selectConnector( evt ) {
                this.set( 'selectedConnector', evt.model.item );
                document.dispatchEvent(new CustomEvent(EventListener.onSelectConnector, { detail: evt.model.item }));
                this.closePopup();
            }

            /**
             *
             */
            _openLink(evt, link) {
                if(link) {
                    let popup = window.open(link, evt.model.label, 'frame=true,nodeIntegration=no');
                    // enable replaceAll only available in later chrome version
                    popup.eval('String.prototype.replaceAll = function (search, replaceWith) { return this.split(search).join(replaceWith) }');
                    // disable onbeforeunload periodically (in case of navigation) to prevent blocking window close
                    let watchdog = setInterval(() => {
                        if(popup.closed) {
                            clearInterval(watchdog);
                        } else {
                            popup.eval(`window.onbeforeunload = evt => undefined;`);
                        }
                    }, 500);
                }
                evt.cancelBubble = true;
                evt.stopPropagation();
            }
            
            /**
             *
             */
            openWebsite(evt) {
                let item = evt.model.item;
                this._openLink(evt, item.url);
            }
            
            /**
             *
             */
            openLogin(evt) {
                let links = evt.model.item.links;
                this._openLink(evt, links ? links.login : undefined);
            }
            
            /**
             *
             */
            openDonation(evt) {
                let links = evt.model.item.links;
                this._openLink(evt, links ? links.donation : undefined);
            }

            /**
             * 
             */
            toggleTag( event ) {
                event.model.item.selected = !event.model.item.selected;
                this.set( 'selectedTags', this.tags.filter( tag => tag.selected ) );
            }

            /**
             *
             */
            filterConnectors( pattern, tags ) {
                let p = ( pattern || '' ).toLowerCase();
                return connector => {
                    let patternMatch = ( !pattern || ( connector.id + connector.label + connector.url ).toLowerCase().includes( p ) );
                    let tagsMatch = ( tags.filter( t => !connector.tags.includes( t.tag ) ).length < 1 );
                    return ( patternMatch && tagsMatch );
                };
            }

            /**
             *
             */
            filterConnectorsByManga( evt ) {
                if( evt.keyCode !== 13 || this.$.mangaPattern.disabled /*this.isMangaFilterButtonDisabled*/ ) {
                    return;
                }

                this.$.mangaPattern.disabled = true;
                let promises = Engine.Connectors.map( connector => {
                    if( typeof connector.findMatchingManga === 'function' ) {
                        return connector.findMatchingManga( this.mangaPattern )
                        .then( result => result ? Promise.resolve( connector ) : Promise.resolve( undefined ) );
                    } else {
                        return Promise.resolve( undefined );
                    }
                } );

                Promise.all( promises )
                .then( values => {
                    this.$.mangaPattern.disabled = false;
                    this.$.mangaPattern.focus();
                    this.set( 'connectorList', values.filter( c => !!c ) );
                } )
                .catch( error => {
                    this.$.mangaPattern.disabled = false;
                    console.error( error );
                } );
            }

            /**
             * 
             */
            clearFilters() {
                this.tags.forEach( tag => tag.selected = false);
                this.set( 'connectorList', Engine.Connectors );
                this.set( 'mangaPattern', '' );
                this.set( 'connectorPattern', '' );
                this.set( 'selectedTags', [] );
            }

            /**
             *
             */
            getConnectorClass( selectedConnector, connector ) {
                return ( selectedConnector === connector ? 'cardSelected' : '' );
            }

            /**
             *
             */
            getTagClass( selectedTags, tag ) {
                return ( selectedTags.includes( tag ) ? 'tagSelected' : '' );
            }

            /**
             *
             */
            getLoginClass(links) {
                return links && links.login ? 'active' : 'disabled';
            }

            /**
             *
             */
            getDonationClass(links) {
                return links && links.donation ? 'active' : 'disabled';
            }
        }
        window.customElements.define(HakunekoConnectors.is, HakunekoConnectors);
    </script>

</dom-module>